home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
program
/
p063b9s.zip
/
UNIT
/
ZSEND.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1997-03-02
|
20KB
|
695 lines
UNIT ZSend;
{╔══════════════════════════════════════════════════════════════════════════╗}
{║ ZModem send routine Last changed: 02.03.97 SA ║}
{║ ║}
{║ (C) Copyright 1989-97 by ║}
{║ Dan Wulff, Jens Sandalgaard, Steen Christensen & S¢ren Ager ║}
{║ ║}
{║ This source may not be given to anybody, without the written permission ║}
{║ from The Portal Team. ║}
{╚══════════════════════════════════════════════════════════════════════════╝}
{$I POPDEFS.INC}
INTERFACE
USES Use32, Dos;
FUNCTION ZModemSend(CONST FName, Alias: PathStr; FSent: Integer; WaZoo: Word): Integer;
IMPLEMENTATION
USES OpCrt, OpDate, OpRoot, OpString, ApTimer,
PoPTypes, Globals, Crc, Com, UnixDate, ZMisc, TransVid, Util, MTask,
LogFile;
FUNCTION ZModemSend;
LABEL
Done, Err_Out;
VAR
CanDo32 : Boolean;
FileName, p, s : PathStr;
FSize : String[10];
MaxBlkLen,
RxBufLen,
Zsize, rc : Word;
Dt : DateTime;
Srec : SEARCHREC;
LastSent : Byte;
OutFile : FILE;
RxFlags,
ZRPosCount : Integer;
LastZRpos,
StrtPos,
udate, TxPos : LongInt;
TxBuf : POINTER;
{
PROCEDURE ZSSendBuffer;
BEGIN
FSendBlock(TxFosBuf^, TxFosPos);
TxFosPos:=0;
END;
}
PROCEDURE ZSSendByte(c: Byte);
BEGIN
IF ((c AND $7f) IN [16, 17, 19, 24]) OR (((c AND $7f)=13) AND ((LastSent AND $7f)=64)) THEN
BEGIN
ComPort^.WriteByte(ZDLE, False);
LastSent:=c XOR 64;
END ELSE
LastSent:=c;
ComPort^.WriteByte(LastSent, False);
END;
{
PROCEDURE ZSSendRawByte(c: Byte);
BEGIN
BT0(TxFosBuf^)[TxFosPos]:=c;
Inc(TxFosPos);
END;
}
(* PROCEDURE ZSSendByte(b: Byte); External;
{$L send} *)
PROCEDURE ZS32SendBinaryHeader(HdrType: Integer; CONST Hdr: HeaderType);
VAR
Crc : LongInt;
n : Byte;
BEGIN
{$IFDEF ZDebug}
AddLog('!','ZS32SendBinaryHeader');
{$ENDIF}
ComPort^.WriteByte(ZBIN32, False);
ZSSendByte(Byte(HdrType));
Crc:=$ffffffff;
Crc:=UpdCrc32(HdrType, Crc);
FOR n:=0 TO 3 DO
BEGIN
ZSSendByte(Hdr[n]);
Crc:=UpdCrc32(Hdr[n], Crc);
END;
Crc := NOT Crc;
FOR n := 0 TO 3 DO
BEGIN
ZSSendByte(Byte(Crc));
Crc := Crc SHR 8;
END;
END;
PROCEDURE ZSSendBinaryHeader(HdrType: Integer; CONST Hdr: HeaderType);
VAR
Crc : Word;
n : Byte;
t : EventTimer;
BEGIN
{$IFDEF ZDebug}
AddLog('!','ZSSendBinaryHeader');
{$ENDIF}
LastSent:=0;
ComPort^.WriteByte(ZPAD, False);
ComPort^.WriteByte(ZDLE, False);
IF CanDo32 THEN
ZS32SendBinaryHeader(HdrType, Hdr)
ELSE
BEGIN
ComPort^.WriteByte(ZBIN, False);
ZSSendByte(Byte(HdrType));
Crc:=UpdCrc16(Byte(HdrType), 0);
FOR n:=0 TO 3 DO
BEGIN
ZSSendByte(Hdr[n]);
Crc:=UpdCrc16(Hdr[n], Crc);
END;
Crc:=UpdCrc16(0, Crc);
Crc:=UpdCrc16(0, Crc);
ZSSendByte(Hi(Crc));
ZSSendByte(Lo(Crc));
END;
ComPort^.FlushTx;
IF HdrType<>ZDATA THEN
BEGIN
NewTimerSecs(t, 2);
WHILE (ComPort^.Carrier) AND (NOT ComPort^.OutEmpty) And (Not TimerExpired(t)) DO
{ GiveUpTime};
IF NOT ComPort^.Carrier THEN ComPort^.PurgeOut;
END;
END;
FUNCTION ZSSyncWithReceiver(NumErrs: Integer): Integer;
VAR
c : Integer;
BEGIN
{$IFDEF BoDebug}
AddLog('!','ZSSyncWithReceiver');
{$ENDIF}
ZSSyncWithReceiver := Error;
REPEAT
c := ZGetHeader(RxHdr);
ComPort^.PurgeIn;
CASE c OF
TimeOut : BEGIN
ShowError('Timeout',True,false,false);
Dec(NumErrs);
IF NumErrs < 0 THEN Exit;
END;
ZCAN,
ZABORT,
ZFIN,
RCDO : BEGIN
ShowError('No Carrier',True,false,false);
Exit;
END;
ZRPOS : BEGIN
IF RxPos = LastZRpos THEN
BEGIN
Dec(ZRPosCount);
IF ZRPosCount < 0 THEN Exit;
END ELSE
ZRPosCount := 10;
LastZRpos := RxPos;
Seek(OutFile, RxPos);
TxPos := RxPos;
ShowError('Resending from '+Long2Str(TxPos),False,False,false);
ZSSyncWithReceiver := c;
Exit;
END;
ZACK,
ZSKIP,
ZRINIT : BEGIN
{ IF c = ZSKIP THEN ShowError('Remote skipped file',False,False,False);}
ZSSyncWithReceiver := c;
Exit;
END;
ELSE BEGIN
ShowError('Scratching head',True,false,false);
ZSSendBinaryHeader(ZNAK, TxHdr);
END;
END;
UNTIL FALSE;
END;
PROCEDURE ZSEndSend;
BEGIN
{$IFDEF ZDebug}
AddLog('!','ZSEndSend');
{$ENDIF}
REPEAT
ZPutLongIntoHeader(0, TxHdr);
ZSSendBinaryHeader(ZFIN, TxHdr);
CASE ZGetHeader(RxHdr) OF
ZFIN : BEGIN
ShowError('Transfer completed',False,false,false);
ComPort^.WriteByte(Byte('O'), False);
ComPort^.WriteByte(Byte('O'), True);
WHILE (ComPort^.Carrier) AND (NOT ComPort^.OutEmpty) DO
GiveUpTime;
IF NOT ComPort^.Carrier THEN ComPort^.PurgeOut;
Exit;
END;
ZCAN,
RCDO,
TimeOut : Exit;
END;
UNTIL FALSE;
END;
PROCEDURE ZS32SendData(Buf: Pointer; Len: Word; FrameEnd: Integer);
VAR
Crc : LongInt;
n : Word;
BEGIN
{$IFDEF ZDebug}
AddLog('!','ZS32SendData');
{$ENDIF}
Crc := $ffffffff;
IF Len>0 THEN
BEGIN
FOR n:=0 TO len-1 DO
BEGIN
ZSSendByte(BufAry(Buf^)[n]);
Crc := UpdCrc32(BufAry(Buf^)[n], Crc);
END;
END;
Crc := UpdCrc32(FrameEnd, Crc);
Crc := NOT Crc;
ComPort^.WriteByte(ZDLE, False);
ComPort^.WriteByte(Byte(FrameEnd), False);
FOR n:=1 TO 4 DO
BEGIN
ZSSendByte(Byte(Crc));
Crc:=Crc SHR 8;
END;
{$IFDEF ZDebug}
AddLog('!','END ZS32SendData');
{$ENDIF}
END;
PROCEDURE ZSSendData(Buf: Pointer; Len: Word; FrameEnd: Integer);
VAR
Crc : Word;
n : Word;
t : EventTimer;
BEGIN
{$IFDEF ZDebug}
AddLog('!','ZSSendData');
{$ENDIF}
IF CanDo32 THEN
ZS32SendData(buf, len, FrameEnd)
ELSE
BEGIN
Crc := 0;
IF Len>0 THEN
BEGIN
FOR n:=0 TO len-1 DO
BEGIN
ZSSendByte(BufAry(Buf^)[n]);
Crc:=UpdCrc16(BufAry(Buf^)[n], Crc);
END;
END;
ComPort^.WriteByte(ZDLE, False);
ComPort^.WriteByte(Byte(FrameEnd), False);
Crc:=UpdCrc16(FrameEnd, Crc);
Crc:=UpdCrc16(0, Crc);
Crc:=UpdCrc16(0, Crc);
ZSSendByte(Hi(Crc));
ZSSendByte(Lo(Crc));
END;
ComPort^.FlushTx;
IF FrameEnd = ZCRCW THEN
BEGIN
ComPort^.WriteByte(XON, True);
NewTimerSecs(t, 2);
WHILE (ComPort^.Carrier) AND (NOT ComPort^.OutEmpty) And (Not TimerExpired(t)) DO
{ GiveUpTime};
IF NOT ComPort^.Carrier THEN ComPort^.PurgeOut;
END;
{$IFDEF ZDebug}
AddLog('!','ZSSendData');
{$ENDIF}
END;
FUNCTION ZSGetReceiverInfo: Integer;
VAR
n : Byte;
BEGIN
{$IFDEF ZDebug}
AddLog('!','ZSGetReceiverInfo');
{$ENDIF}
FOR n := 0 TO 9 DO
BEGIN
CASE ZGetHeader(RxHdr) OF
ZCHALLENGE : BEGIN
ZPutLongIntoHeader(RxPos, TxHdr);
ZSendHexHeader(ZACK, TxHdr);
Continue;
END;
ZCOMMAND : BEGIN
ZPutLongIntoHeader(0, TxHdr);
ZSendHexHeader(ZRQINIT, TxHdr);
Continue;
END;
ZRINIT : BEGIN
RxFlags := 255 AND RxHdr[ZF0];
RxBufLen := (Word(RxHdr[ZP1] SHR 8)) + RxHdr[ZP0];
CanDo32 := (RxFlags AND CANFC32) = CANFC32;
IF CanDo32 THEN ShowErrorCheckingMethod('Z-Send CRC32',false) ELSE
ShowErrorCheckingMethod('Z-Send CRC16',false);
ZSGetReceiverInfo := ok;
Exit;
END;
ZCAN,
RCDO,
TimeOut : BEGIN
ShowError('TIMEOUT',True,false,false);
ZSGetReceiverInfo := Error;
Exit;
END;
ZRQINIT : IF RxHdr[ZF0] = ZCOMMAND THEN Continue;
ELSE ZSendHexHeader(ZNAK, TxHdr);
END;
END;
ZSGetReceiverInfo := Error;
END;
FUNCTION ZSSendFileData(WaZoo: Integer) : Integer;
LABEL
Oops, SomeMore, WaitAck;
VAR
c, e, newcnt : Integer;
BlkLen, MaxBlkLen, GoodBlks, GoodNeeded : Word;
t : EventTimer;
BEGIN
{$IFDEF ZDebug}
AddLog('!','ZSSendFileData');
{$ENDIF}
newcnt := 1; GoodBlks := 0; GoodNeeded := 1;
IF (ComPort^.GetBaudRate>=0) And (ComPort^.GetBaudRate<300) THEN
MaxBlkLen:=128
ELSE
MaxBlkLen:=ComPort^.GetBaudRate Div 300 * 256;
IF MaxBlkLen>WaZooMax THEN maxBlkLen:=WaZooMax;
IF (WaZoo=0) And (MaxBlkLen>KSize) THEN MaxBlkLen:=KSize;
IF (RxBufLen <> 0) AND (MaxBlkLen > RxBufLen) THEN
MaxBlkLen := RxBufLen;
BlkLen := MaxBlkLen;
SomeMore:
{$IFDEF ZDebug}
AddLog('!','L01');
{$ENDIF}
IF ComPort^.Keypressed THEN
BEGIN
WaitAck:
{$IFDEF ZDebug}
AddLog('!','L02');
{$ENDIF}
c := ZSSyncWithReceiver(1);
CASE c OF
ZSKIP : BEGIN
ShowError('Remote skipped file',False,False,false);
ZSSendFileData := c;
Exit;
END;
ZACK : ;
ZRPOS : BEGIN
IF BlkLen>128 THEN BlkLen:=BlkLen SHR 2 ELSE BlkLen:=64;
GoodBlks := 0;
IF (GoodNeeded SHL 1) > 8 THEN
GoodNeeded := 8
ELSE
GoodNeeded := GoodNeeded SHL 1;
END;
ZRINIT : BEGIN
ZSSendFileData := ok;
Exit;
END;
TimeOut : ;
ELSE BEGIN
ShowError('Transfer cancelled',False,true,false);
ZSSendFileData := Error;
Exit;
END;
END;
ZUnCorkTransmitter;
ComPort^.WriteByte(XON, True);
WHILE ComPort^.Keypressed DO
BEGIN
CASE ZTimedRead OF
Can,
RCDO,
ZPAD : GOTO WaitAck;
END;
END;
END;
newcnt := RxBufLen;
ZPutLongIntoHeader(TxPos, TxHdr);
ZSSendBinaryHeader(ZDATA, TxHdr);
REPEAT
IF GotESC THEN
BEGIN
ComPort^.PurgeOut;
ComPort^.SetXOn(Off);
ZSendCan;
NewTimerSecs(t, 2);
WHILE (NOT TimerExpired(t)) AND (NOT ComPort^.OutEmpty) AND (ComPort^.Carrier) DO
GiveUpTime;
ComPort^.SetXOn(On);
ShowError('Keybord ESC',False,true,false);
GOTO Oops;
END;
IF NOT ComPort^.Carrier THEN GOTO Oops;
BlockRead(OutFile, TxBuf^, BlkLen, c);
ShowBlockSize(c, False);
IF c <> Zsize THEN Zsize := c;
IF c<BlkLen THEN
BEGIN
e:=ZCRCE
END ELSE
BEGIN
newcnt:=newcnt-c;
IF (RxBufLen<>0) AND (newcnt<=0) THEN e:=ZCRCW ELSE e:=ZCRCG;
END;
ZSSendData(TxBuf, c, e);
Inc(TxPos, c);
ShowCurrentByte(TxPos,false);
Inc(GoodBlks);
IF (BlkLen < MaxBlkLen) AND (GoodBlks > GoodNeeded) THEN
BEGIN
IF (BlkLen SHL 1) < MaxBlkLen THEN
BlkLen := BlkLen SHL 1
ELSE
BlkLen := MaxBlkLen;
GoodBlks := 0;
END;
IF NOT ComPort^.Carrier THEN GOTO Oops;
IF e = ZCRCW THEN GOTO WaitAck;
WHILE ComPort^.Keypressed DO
BEGIN
CASE ZTimedRead OF
Can,
RCDO,
ZPAD : BEGIN
ShowError('Trouble?',True,false,false);
ComPort^.PurgeOut;
ZSSendData(TxBuf, 0, ZCRCE);
GOTO WaitAck;
END;
END;
END;
UNTIL (e <> ZCRCG);
REPEAT
ZPutLongIntoHeader(TxPos, TxHdr);
ZSSendBinaryHeader(ZEOF, TxHdr);
CASE ZSSyncWithReceiver(7) OF
ZACK : Continue;
ZRPOS : GOTO SomeMore;
ZRINIT : BEGIN
ZSSendFileData := ok;
Exit;
END;
ZSKIP : BEGIN
ShowError('Remote skipped file',False,true,false);
ZSSendFileData := c;
Exit;
END;
ELSE BEGIN
Oops:
ShowError('Transfer cancelled',False,true,false);
Break;
END;
END;
UNTIL FALSE;
ZSSendFileData := Error;
END;
FUNCTION ZSSendFile(BLen, WaZoo: Word): Integer;
LABEL
Again;
VAR
t : EventTimer;
c : Integer;
BEGIN
{$IFDEF ZDebug}
AddLog('!','ZSSendFile');
{$ENDIF}
ZSSendFile := Error;
REPEAT
IF GotESC THEN
BEGIN
ComPort^.PurgeOut;
ComPort^.SetXOn(Off);
ZSendCan;
NewTimerSecs(t, 2);
WHILE (NOT TimerExpired(t)) AND (NOT ComPort^.OutEmpty) AND (ComPort^.Carrier) DO
GiveupTime;
ComPort^.SetXOn(On);
ShowError('Keyboard ESC',False,true,false);
Exit;
END ELSE
BEGIN
IF NOT ComPort^.Carrier THEN Break;
TxHdr[ZF0]:=LZCONV;
TxHdr[ZF1]:=LZMANAG;
TxHdr[ZF2]:=LZTRANS;
TxHdr[ZF3]:=0;
ZSSendBinaryHeader(ZFILE, TxHdr);
ZSSendData(TxBuf, BLen, ZCRCW);
Again:
{$IFDEF ZDebug}
AddLog('!','L03');
{$ENDIF}
c := ZGetHeader(RxHdr);
CASE c OF
ZRINIT : BEGIN
{ goto again; }
c := ZGetByte(50);
WHILE c > 0 DO
BEGIN
IF c = ZPAD THEN GOTO Again;
c:=ZGetByte(50);
END;
Continue;
END;
ZCAN,
RCDO,
TimeOut,
ZFIN,
ZABORT : BEGIN
ShowError('Transfer aborted',False,true,false);
Break;
END;
ZSKIP : BEGIN
ZSSendFile := c;
Break;
END;
ZRPOS : BEGIN
ShowCurrentFileName(FileName, RxPos, SRec.Size, 96, False);
Seek(OutFile, RxPos);
IF IoResult <> 0 THEN Break;
ComPort^.PurgeOut;
ComPort^.SetXOn(Off);
ComPort^.WriteByte(XON, True);
ComPort^.SetXOn(On);
LastZRpos := RxPos;
StrtPos := RxPos;
TxPos := RxPos;
ZRPosCount := 10;
ComPort^.PurgeIn;
{$IFDEF ZDebug}
AddLog('!','F¥R ZSSendFileData');
{$ENDIF}
ZSSendFile := ZSSendFileData(WaZoo);
{$IFDEF ZDebug}
AddLog('!','EFTER ZSSendFileData');
{$ENDIF}
Break;
END;
ELSE Continue;
END; {case}
END; {else}
UNTIL FALSE;
{$IFDEF ZDebug}
AddLog('!','END ZSSendFile');
{$ENDIF}
END;
BEGIN
{$IFDEF ZDebug}
AddLog('!','ZModemSend');
{$ENDIF}
ComPort^.SetBreak(Off);
{ IF FCtrlC(0) THEN ;}
ComPort^.SetXon(Off); { FTransmitByte(XOn);} ComPort^.SetXOn(On);
TxBuf:=NIL; ZSize := 0;
RxBufLen:=0;
CanDo32:=FALSE;
LastSent:=0;
CASE FSent OF
0,
NOTHING_TO_DO :
BEGIN
IF FSent = 0 THEN
BEGIN
ZPutString('rz' + Char(Cr));
ZPutLongIntoHeader(LongInt(0), TxHdr);
ZSendHexHeader(ZRQINIT, TxHdr);
END;
RxTimeOut := 200;
IF ZSGetReceiverInfo = Error THEN
BEGIN
ComPort^.SetXOn(Off);
ComPort^.SetXOn(On);
ZModemSend := ZFALSE;
ShowError('Can''t get attention',True,true,false);
Exit;
END;
END;
END;
RxTimeOut := LongInt(LongInt(614400) DIV ComPort^.GetBaudRate);
IF RxTimeOut < 100 THEN RxTimeOut := 100;
rc := ZTRUE;
FileName := FName;
IF FName = '' THEN GOTO Done;
FINDFIRST(FileName, AnyFile, Srec);
IF DOSERROR <> 0 THEN
BEGIN
FindClose(SRec);
ComPort^.SetXOn(Off);
ComPort^.SetXOn(On);
ZModemSend:=ZTRUE;
Exit;
END;
FindClose(SRec);
{ Check for TTY }
IF Alias<>'' THEN p:=Alias ELSE p:=FileName;
p:=JustFileName(p);
FSize:=Long2Str(Srec.size);
UnPackTime(SRec.Time, Dt);
WITH Dt DO
udate:=GetUnixDate(Year, Month, Day, Hour, Min, Sec);
s:=OctalL(UDate);
WHILE COPY(s,1,2)='00' DO
Delete(s,1,1);
s:=StLoCase(p)+#0+FSize+' '+s+ ' 00';
IF (ComPort^.GetBaudRate >= 0) AND (ComPort^.GetBaudRate < 300) THEN
MaxBlkLen:=128
ELSE
MaxBlkLen := ComPort^.GetBaudRate DIV 300 * 256;
IF (MaxBlkLen > WAZOOMAX) THEN MaxBlkLen := WAZOOMAX;
IF (WaZoo=0) AND (MaxBlkLen>KSIZE) THEN MaxBlkLen:=KSIZE;
IF NOT GetMemCheck(TxBuf, MaxBlkLen) THEN
BEGIN
ShowError('ZS-Not enough memory',False,True,false);
ZModemSend := Error;
{ IF TxBuf<>NIL THEN FreeMem(TxBuf, MaxBlkLen);}
Exit;
END;
FillChar(TxBuf^, MaxBlkLen, 0);
Move(s[1], TxBuf^, Length(s));
Assign(OutFile, FileName); FileMode:=ShareRead+ShareDenyW;
Reset(OutFile, 1);
IF IOResult=5 THEN
BEGIN
AddLog('!','Access denied to: '+FileName);
FileName:='';
{ FName:='';}
GOTO Err_Out;
END;
CASE ZSSendFile(Length(s), WaZoo) OF
Error : GOTO Err_Out;
ok : BEGIN
FileSent(FileName,'Z'+CrcStr(CanDo32),False);
GOTO Done;
END;
ZSKIP : BEGIN
AddLog('+', 'Remote refused ' + FileName);
rc := SPEC_COND;
GOTO Done;
END;
ELSE GOTO Done;
END;
Err_Out:
rc := ZFALSE;
Done:
{$IFDEF ZDebug}
AddLog('!','L04');
{$ENDIF}
IF FileName<>'' THEN Close(OutFile);
IF IoResult = 0 THEN ;
IF TxBuf <> NIL THEN FreeMem(TxBuf, MaxBlkLen);
ComPort^.SetXOn(Off);
ComPort^.SetXOn(On);
IF FSent < 0 THEN ZSEndSend;
ZModemSend := rc;
END;
END.